# -*- coding: utf-8 -*-
"""GitLab代码拉取模块"""

import os
import subprocess
from pathlib import Path
from typing import Dict, List
from urllib.parse import urlparse, urlunparse
from .config import config_manager


class CodeFetcher:
    """代码拉取器"""
    
    def __init__(self, codes_dir="codes"):
        """
        初始化代码拉取器
        
        Args:
            codes_dir: 代码存放目录
        """
        self.codes_dir = Path(codes_dir)
        self.codes_dir.mkdir(parents=True, exist_ok=True)
        
        # 获取GitLab配置
        gitlab_config = config_manager.get_gitlab_config()
        
        # 优先使用private_token，其次使用username+password
        self.private_token = gitlab_config.get('private_token', '')
        self.username = gitlab_config.get('username', '')
        self.password = gitlab_config.get('password', '')
        self.default_branch = gitlab_config.get('default_branch', 'test')
    
    def _build_auth_url(self, repo_url: str) -> str:
        """
        构建带认证信息的Git URL
        
        优先级：private_token > username+password
        
        Args:
            repo_url: 原始仓库URL
        
        Returns:
            带认证信息的URL
        """
        # 解析URL
        parsed = urlparse(repo_url)
        
        # URL编码
        from urllib.parse import quote
        
        # 优先使用private_token (GitLab支持使用oauth2:token@host格式)
        if self.private_token:
            # GitLab支持使用 oauth2:token 或 gitlab-ci-token:token 格式
            encoded_token = quote(self.private_token, safe='')
            netloc_with_auth = f"oauth2:{encoded_token}@{parsed.netloc}"
        # 其次使用username+password
        elif self.username and self.password:
            encoded_username = quote(self.username, safe='')
            encoded_password = quote(self.password, safe='')
            netloc_with_auth = f"{encoded_username}:{encoded_password}@{parsed.netloc}"
        else:
            # 没有认证信息，返回原URL
            return repo_url
        
        # 重新组装URL
        auth_url = urlunparse((
            parsed.scheme,
            netloc_with_auth,
            parsed.path,
            parsed.params,
            parsed.query,
            parsed.fragment
        ))
        
        return auth_url
    
    def fetch_project(self, project: Dict) -> Dict:
        """
        拉取单个项目代码
        
        Args:
            project: 项目配置字典，包含name, repo_url, default_branch等
        
        Returns:
            结果字典，包含success, path, message等
        """
        project_name = project.get('name', '')
        repo_url = project.get('repo_url', '')
        branch = project.get('default_branch') or project.get('branch') or self.default_branch
        
        if not project_name or not repo_url:
            return {
                'success': False,
                'project': project_name,
                'error': '项目配置不完整'
            }
        
        # 项目本地路径
        project_path = self.codes_dir / project_name
        
        try:
            # 如果目录已存在，先删除
            if project_path.exists():
                print(f"清理旧代码: {project_path}")
                import shutil
                shutil.rmtree(project_path)
            
            # 构建带认证的URL
            auth_url = self._build_auth_url(repo_url)
            
            # 执行git clone
            print(f"正在克隆项目: {project_name} (分支: {branch})")
            cmd = [
                'git', 'clone',
                '--branch', branch,
                '--depth', '1',  # 只克隆最新一次提交，加快速度
                auth_url,
                str(project_path)
            ]
            
            # 执行命令
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                timeout=300  # 5分钟超时
            )
            
            if result.returncode != 0:
                error_msg = result.stderr or result.stdout
                return {
                    'success': False,
                    'project': project_name,
                    'error': f'Git clone失败: {error_msg}'
                }
            
            # 删除.git目录以节省空间
            git_dir = project_path / '.git'
            if git_dir.exists():
                import shutil
                shutil.rmtree(git_dir)
            
            return {
                'success': True,
                'project': project_name,
                'path': str(project_path),
                'branch': branch,
                'message': f'成功拉取项目 {project_name}'
            }
            
        except subprocess.TimeoutExpired:
            return {
                'success': False,
                'project': project_name,
                'error': 'Git clone超时（超过5分钟）'
            }
        except Exception as e:
            return {
                'success': False,
                'project': project_name,
                'error': f'拉取失败: {str(e)}'
            }
    
    def fetch_projects(self, projects: List[Dict]) -> Dict:
        """
        批量拉取多个项目代码
        
        Args:
            projects: 项目配置列表
        
        Returns:
            结果字典，包含success, results等
        """
        if not projects:
            return {
                'success': False,
                'error': '没有要拉取的项目'
            }
        
        results = []
        success_count = 0
        
        for project in projects:
            result = self.fetch_project(project)
            results.append(result)
            if result['success']:
                success_count += 1
        
        return {
            'success': success_count > 0,
            'total': len(projects),
            'success_count': success_count,
            'failed_count': len(projects) - success_count,
            'results': results,
            'codes_dir': str(self.codes_dir)
        }
    
    def get_project_code(self, project_name: str) -> str:
        """
        读取项目代码内容（用于分析）
        
        Args:
            project_name: 项目名称
        
        Returns:
            项目代码的文本表示
        """
        project_path = self.codes_dir / project_name
        
        if not project_path.exists():
            return f"项目 {project_name} 的代码不存在"
        
        # 收集项目文件
        code_content = []
        code_content.append(f"# 项目: {project_name}\n")
        code_content.append(f"# 路径: {project_path}\n\n")
        
        # 遍历项目文件
        for root, dirs, files in os.walk(project_path):
            # 跳过一些不需要的目录
            dirs[:] = [d for d in dirs if d not in [
                'node_modules', 'venv', '__pycache__', '.git', 
                'dist', 'build', 'coverage', '.pytest_cache'
            ]]
            
            for file in files:
                # 只读取代码文件
                if not file.endswith(('.py', '.js', '.ts', '.jsx', '.tsx', 
                                     '.java', '.go', '.vue', '.html', '.css',
                                     '.scss', '.less', '.json', '.yaml', '.yml')):
                    continue
                
                file_path = Path(root) / file
                rel_path = file_path.relative_to(project_path)
                
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        content = f.read()
                    
                    code_content.append(f"\n## 文件: {rel_path}\n")
                    code_content.append(f"```\n{content}\n```\n")
                    
                except Exception as e:
                    code_content.append(f"\n## 文件: {rel_path} (读取失败: {e})\n")
        
        return '\n'.join(code_content)
    
    def clean_codes(self):
        """清理codes目录"""
        if self.codes_dir.exists():
            import shutil
            shutil.rmtree(self.codes_dir)
            self.codes_dir.mkdir(parents=True, exist_ok=True)
            return {'success': True, 'message': '代码目录已清理'}
        return {'success': True, 'message': '代码目录不存在'}

